package net.anzix.osgi.jabberconsole.internal;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.felix.shell.ShellService;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.knopflerfish.service.console.ConsoleService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

/**
 * Extension of the default OSGi bundle activator
 */
public final class Activator implements BundleActivator {

    XMPPConnection connection;
    BundleContext bc;

    private String runCommand(String cmdMessage) throws Exception {
        String cmdType = new StringTokenizer(cmdMessage, " ").nextToken();

        //find Felix commmands
        ServiceReference[] references = bc.getServiceReferences("org.apache.felix.shell.ShellService", null);
        if (references != null) {
            for (int i = 0; i < references.length; i++) {
                ServiceReference serviceReference = references[i];
                ShellService service = (ShellService) bc.getService(serviceReference);
                for (String command : service.getCommands()) {
                    if (command.equals(cmdType)) {
                        ByteArrayOutputStream outStr = new ByteArrayOutputStream();
                        ByteArrayOutputStream errStr = new ByteArrayOutputStream();
                        PrintStream out = new PrintStream(outStr);
                        PrintStream err = new PrintStream(errStr);
                        service.executeCommand(cmdMessage, out, err);
                        StringBuffer response = new StringBuffer();
                        response.append(outStr.toString());
                        if (errStr.toString().length() > 0) {
                            response.append("\nCommand '" + cmdType + "' returned with error: \n");
                            response.append(errStr.toString());
                        }
                        return response.toString();
                    }
                }
            }
        }


        //find Knopflerfish commands

        ServiceReference knopflerServRefs = bc.getServiceReference("org.knopflerfish.service.console.ConsoleService");
        if (knopflerServRefs != null) {
            ConsoleService service = (ConsoleService) bc.getService(knopflerServRefs);
            return service.runCommand(cmdMessage);
        }
        //find Equinox commmands
        try {
            ServiceReference[] equinoxServRefs = bc.getServiceReferences("org.eclipse.osgi.framework.console.CommandProvider", null);
            if (equinoxServRefs != null && equinoxServRefs.length > 0) {
                CommandInterpreterImpl equinoxInterpreter = new CommandInterpreterImpl(cmdMessage, bc);
                equinoxInterpreter.execute();
                return equinoxInterpreter.getOutput();
            }
        } catch (IllegalArgumentException ex) {
            System.out.println("No such method");
        //no such method
        }

        return "No such command: " + cmdType;

    }

    /**
     * Called whenever the OSGi framework starts our bundle
     */
    public void start(BundleContext bc) throws Exception {
        this.bc = bc;
        System.out.println("STARTING net.anzix.osgi.jabberconsole");

        String server = bc.getProperty("net.anzix.osgi.jabberconsole.server");
        String user = bc.getProperty("net.anzix.osgi.jabberconsole.user");
        String password = bc.getProperty("net.anzix.osgi.jabberconsole.password");
        connection = new XMPPConnection(server);
        connection.connect();
        connection.login(user, password);

        connection.getRoster().setSubscriptionMode(SubscriptionMode.accept_all);

        connection.getChatManager().addChatListener(new ChatManagerListener() {

            public void chatCreated(Chat chat, boolean arg1) {
                chat.addMessageListener(new MessageListener() {

                    public void processMessage(Chat ch, Message message) {
                        if (message.getBody().length() == 0) {
                            return;
                        }
                        try {
                            ch.sendMessage(runCommand(message.getBody()));
                        } catch (Exception ex) {
                            try {
                                ch.sendMessage("Error on execution: " + ex.getMessage());
                                Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex);
                            } catch (XMPPException ex1) {
                                Logger.getLogger(Activator.class.getName()).log(Level.SEVERE, null, ex1);
                            }

                        }
                    }
                });
            }
        });


    }

    /**
     * Called whenever the OSGi framework stops our bundle
     */
    public void stop(BundleContext bc) throws Exception {
        System.out.println("STOPPING net.anzix.osgi.jabberconsole");
        connection.disconnect();

    }
}

